/**
 * 
 */
package la.ge.server.servlets.gs2ge;

import java.io.IOException;
import java.util.Collection;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;

import la.common.CommonException;
import la.common.xml.Node2String;
import la.common.xml.XMLHelper;
import la.ge.kml.ErrorReportKMLBuilder;
import la.ge.kml.KMLConstants;
import la.ge.kml.KMLHelper;
import la.ge.server.GeServerContext;
import la.ge.server.gs2ge.GSResultRecs2KMLNetLinks;
import la.ge.server.servlets.gs2ge.util.Util;
import la.gs.GSDocParseResult;
import la.gs.GSExtractor;
import la.gs.GSResultRec;
import la.gs.GSearchCriteria;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * Google search result viewer 
 * @author labile
 *
 */
@SuppressWarnings("serial")
public class GetPlainGSResultServlet extends HttpServlet
{
	private static Log logger = LogFactory.getLog( GetPlainGSResultServlet.class );
	
	/**
	 * http url parameter:
	 * {@link GSearchCriteria} fields(optional, null for use setting)
	 * int firstGSResultIndex(optional, null for 0)
	 * int maxResultQty(optional, null for 10)
	 */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
    	Util.trySetURLQueryCharset( request );
    	
    	GeServerContext geServerContext = (GeServerContext) this.getServletContext().getAttribute( GeServerContext.ATTRIB_NAME );
    	GSearchCriteria searchCriteria = Util.extractSearchCriteria(request);
    	if( searchCriteria.getKeyword() == null ) {//invalid searchCriteria
    		synchronized (geServerContext.getGsSetting()) {
        		searchCriteria = geServerContext.getGsSetting().searchCriteria;
			}
    	}
    	
		response.setContentType( KMLConstants.KML_MIME );
		response.setCharacterEncoding( "utf-8" );
		response.setStatus(HttpServletResponse.SC_OK);
		
    	if( searchCriteria == null ) {// no default setting & no instant parameter
    		ErrorReportKMLBuilder errorReportKMLBuilder = new ErrorReportKMLBuilder();
    		response.getWriter().print( errorReportKMLBuilder.build( "no default setting & no instant parameter" ) );
    		return;
    	}
    	
   	  	int firstGSResultIndex = 0;
   	  	try {
   	  		firstGSResultIndex = Integer.parseInt( request.getParameter( "firstGSResultIndex" ) );
   	  	}catch(Exception e) {/*use default value*/}
		int maxResultQty = 10;
   	  	try {
   	  	maxResultQty = Integer.parseInt( request.getParameter( "maxResultQty" ) );
   	  	}catch(Exception e) {/*use default value*/}
    	
		try {
			response.getWriter().println(gen( searchCriteria, firstGSResultIndex, maxResultQty ));
		} catch ( CommonException e ) {
    		ErrorReportKMLBuilder errorReportKMLBuilder = new ErrorReportKMLBuilder();
    		response.getWriter().print( errorReportKMLBuilder.build( e ) );
		}
    }
    
    public static Document genDoc(GSearchCriteria searchCriteria, int firstGSResultIndex, int maxResultQty, XMLHelper xmlHelper) throws CommonException {
		try {
			GSExtractor extractor = new GSExtractor();
			GSDocParseResult docParseResult = extractor.extractFromGoogle( searchCriteria, firstGSResultIndex, maxResultQty );
			
			logger.debug( docParseResult );
			
			return genDoc(docParseResult.getRecords(), xmlHelper);
		} catch ( Exception e ) {
			throw new CommonException( e );
		}
	}
    
    public static Document genDoc(Collection<GSResultRec> gsResults, XMLHelper xmlHelper) {
    	try {
			XPath xpath = xmlHelper.createXMLPath();
			xpath.setNamespaceContext( KMLHelper.KML20XMLNSContext );

			Element eDocument = null;
			Document doc = xmlHelper.sureLoadDocFromClassLoader( "/la/ge/server/servlets/gs2ge/GetPlainGSResultServlet.xml" );
			eDocument = (Element) xpath.compile( "/kml:kml/kml:Document" ).evaluate( doc, XPathConstants.NODE );

	    	GSResultRecs2KMLNetLinks resultRecs2KMLNetLinks = new GSResultRecs2KMLNetLinks();
			Collection<Element> eActualNetworkLinks = resultRecs2KMLNetLinks.act( gsResults, doc );
			
			eDocument.appendChild( doc.createComment( "add the actual <NetworkLink>s" ) );
			for(Node e : eActualNetworkLinks) {
				e = doc.importNode( e, true );
				eDocument.appendChild( e );
			}
			
			return eDocument.getOwnerDocument();
		} catch (Exception e) {
			throw new RuntimeException( e );
		}
    }
    
	public String gen(GSearchCriteria searchCriteria, int firstGSResultIndex, int maxResultQty) throws CommonException {
		String result = Node2String.node2String(
				genDoc(searchCriteria, firstGSResultIndex, maxResultQty, new XMLHelper()) );
		logger.debug(result);
		return result;
	}
	
	
}